//! This is a simple example of 
//! 1. create_signal + 闭包
//! 2. create_resource + async fn
//! 3. #[server("SendNortify","/api")]
//! 4. create_action + async fn.
//! 5. Await 组件
//! 
use common::ChatHistory;
use leptos::*;
use serde::*;
use chrono::prelude::*;
use leptos_meta::Title;
use anyhow::bail;
use web_sys;
// use leptos::{html::Input, *};
use thiserror::Error;
use anyhow::Result;
use reqwest::header::HeaderMap;
// use gloo_storage::{LocalStorage, Storage};

#[component]
pub fn ChatView() -> impl IntoView {
  
    let (msg, set_msg) = create_signal(String::new());        
    let his_init:Vec<ChatHistory> = vec![];
    let (his, set_his) = create_signal(his_init );
    
    spawn_local(async move {            
          let r = get_chat_glm().await;          
          if let Ok(r) = r {               
            if r.len() > 0 {
              set_his.set(r);
            }
          }      
      });

    view! {
      <div align="center">          
      <div>"把问题交给后端，从后端发起Chat请求，保存结果，并返回给前端的逻辑： "</div>
      <input type="text" size="50" placeholder="input your question!"  id="inputbox" on:input=move |ev| set_msg.set(event_target_value(&ev)) />          
        <button  style="margin:10px"   on:click=move |_| {
          let new_input = msg.get();
          logging::log!("input is {}", new_input);
          if new_input.len() > 0 {
            
            let chatview = document().get_element_by_id("waitingview").unwrap();
            chatview.set_inner_html("<div>  <p class=\"wait-tips\">Waiting ... ...!</p> </div>");

            spawn_local(async move {            
              let r = chat_with_glm(&new_input).await;             
              if let Ok(r) = r {               
                  if r.len() > 0 {
                    set_his.set(r);
                  }
              }            
              let chatview = document().get_element_by_id("waitingview").unwrap();
              chatview.set_inner_html("<br/>");
              reset_input("inputbox", "");
          });

          }else{
            logging::log!("input is empty! {}", get_input_value("inputbox"));
          }          
        }>提问</button>       
      </div>

      <div id="waitingview"> </div>  
      <div id="chatview" align="left"> 
      <Transition>  
      { move|| {
          let hiss = his.get();
          hiss.into_iter().map(|s| {
                      view! {
                              <div class="chat-line" >
                                  <strong>Ask:</strong>
                                  <p>
                                  {s.question}" [" { s.timestamp } "]"
                                  </p>
                              </div>
                              <div class="chat-line">
                                  <strong>Answer:</strong>
                                  <p>{s.response}</p>
                                  <hr style= "border:1px dashed;" />
                              </div>
                          }
                      })
                      .collect::<Vec<_>>()       
            }
      }
      </Transition>

    </div>       
      
    }

}

  /**
   * 重置指定ID的输入框（type=input）的值。
   * @param input_id
   * @param val
   * @spec: 这里提供了一种基于 js_sys::eval(js_code) ，执行js代码的方法或途径。
   */
  fn reset_input(input_id: &str, val:&str) {    
    let js_src = format!("document.getElementById('{}').value ='{}'", input_id, val); 
    web_sys::js_sys::eval(&js_src).ok();  
  }
  /**
   * 获取指定ID的输入框（type=input）的值。
   * @param input_id
   * @spec: 这里提供了一种基于 js_sys::eval(js_code) ，执行js代码的方法或途径。
   */
  fn get_input_value(input_id: &str)->String {  
    let js_src = format!("document.getElementById('{}').value", input_id); 
    let s = web_sys::js_sys::eval(&js_src).unwrap();  
    match s.as_string(){
      Some(s) => return s,
      None => return "".to_string(),
    }
  }
  /**
   * 简单调用GLM开方接口，采用glm-4-flash模型，进行对话。
   */
async fn chat_with_glm(msg: &str) -> anyhow::Result< Vec< ChatHistory >> {

    let host = window().location().host().unwrap();
    // let r = web_sys::js_sys::eval("window.location.host");
    let api = format!("http://{}/api/chat_glm?question={}", host, msg);
    logging::log!("api = {:#?}", api);
    let client = reqwest::Client::new();
    let mut headers = HeaderMap::new();
    headers.insert("Authorization", "Bearer abc".parse()?);
    headers.insert("Content-Type", "application/json; charset=utf-8".parse()?);


    let r: Vec<ChatHistory> = client
        .post(&api)
        .headers(headers)
        .send()
        .await?
        .json()
        .await?;

    logging::log!("get chat history, count={}", r.len());        
    return Ok(r);
  }
  
  async fn get_chat_glm() -> anyhow::Result< Vec< ChatHistory >> {

    let host = window().location().host().unwrap();
    // let r = web_sys::js_sys::eval("window.location.host");
    let api = format!("http://{}/api/get_glm_chat", host);
    logging::log!("api = {:#?}", api);
    let client = reqwest::Client::new();
    let mut headers = HeaderMap::new();
    headers.insert("Authorization", "Bearer abc".parse()?);
    headers.insert("Content-Type", "application/json; charset=utf-8".parse()?);


    let r: Vec<ChatHistory> = client
        .get(&api)
        .headers(headers)
        .send()
        .await?
        .json()
        .await?;

    logging::log!("get chat history, count={}", r.len());        
    return Ok(r);
  }